#include "Character.h"

Character::Character() {

}

Character::~Character() {
    Utils::safeRelease(this->cost);
    Utils::safeRelease(this->dps);
    Utils::safeRelease(this->upgradeLevelEarn);
    Utils::safeRelease(this->moneyPerAtt);
    Utils::safeRelease(this->moneyPerSec);
}

bool Character::init() {
    this->characterId = -1;
    this->name = "";
    this->lastNoti = 0;
    this->hasNoti = false;
    this->upgradeAvailable = false;
    
    this->cost = BigNumber::create();
    CC_SAFE_RETAIN(this->cost);
    this->cost->initialize(0);
    
    this->attackTime = -1;
    
    this->dps = BigNumber::create();
    CC_SAFE_RETAIN(this->dps);
    this->dps->initialize(0);
    
    this->upgradeLevelEarn = __Array::create();
    CC_SAFE_RETAIN(this->upgradeLevelEarn);
    
    this->characterMoney = NULL;
    this->moneyPerSec = NULL;
    this->moneyPerAtt = NULL;
    this->level = -1;
    this->upgradeLevel = 0;
    this->timeToNextUpgrade = 0.0f;
    return true;
}

void Character::initCharacter(int characterId, int specialLevel) {
    this->characterId = characterId;
    //INIT FACE
    if(this->characterId != CHAR_KID) {
        Face* mainFace = new Face();
        mainFace->setName((char*) FACE_MAIN);
        char* normalStatePattern = (char*) "";
        normalStatePattern = this->getAnimation();
        char normalSpriteFrame[200];
        sprintf(normalSpriteFrame, normalStatePattern, specialLevel);
        mainFace->initWithSpriteFrameName(normalSpriteFrame);
        
        // state normal
        Action* normalState = mainFace->createState(normalStatePattern, specialLevel, specialLevel, 1, false, false);
        mainFace->registerState((char*) STATE_NORMAL, normalState);
        
        mainFace->setState(normalState);
        this->faces->addObject(mainFace);
        
        //INIT BODY
        RectBody* body = new RectBody(mainFace->getContentSize().width, mainFace->getContentSize().height);
        CC_SAFE_RETAIN(body);
        this->body = body;
        if (characterId == CHAR_CEO) {
            body->setAnchorPoint(Point(0.5,0));
            body->setPosition(Point(650, 20));
        } else if (characterId == CHAR_GHOST) {
            body->setPosition(Point(670, 393));
        } else if (characterId == CHAR_GOD) {
            body->setPosition(Point(461, 327));
        } else if (characterId == CHAR_GOVERMENT) {
            body->setPosition(Point(850, 354));
        } else if (characterId == CHAR_GRANDMA) {
            body->setAnchorPoint(Point(0.5,0));
            body->setPosition(Point(340, 10));
        } else if (characterId == CHAR_HACKER) {
            body->setPosition(Point(200, 156));
        } else if (characterId == CHAR_KID) {
            body->setPosition(Point(868, 150));
        } else if (characterId == CHAR_SUPER_MAN) {
            body->setPosition(Point(100, 388));
        } else if (characterId == CHAR_GAME_DEV) {
            body->setPosition(Point(102,122));
        }
    }
//    else if (this->characterId == CHAR_SUPER_MAN){
//        FaceBone* mainFace = new FaceBone(ANI_JSON_SUPER_MAN, ANI_ATLAS_SUPER_MAN);
//        mainFace->setVisible(true);
//        mainFace->setAnimation("fly", true);
//        RectBody* body = new RectBody(168,234);
//        CC_SAFE_RETAIN(body);
//        this->body = body;
//        this->body->setPosition(Point(200,0));
//        this->faces->addObject(mainFace);
//    }
    else if (this->characterId == CHAR_KID) {
        FaceBone* mainFace = new FaceBone(ANI_JSON_KID, ANI_ATLAS_KID);
        mainFace->setVisible(true);
        mainFace->setAnimation("shoot", true);
        mainFace->setSkin("lv3");
        mainFace->setSlotsToSetupPose();
        RectBody* body = new RectBody(230,205);
        body->setFlipX(true);
        CC_SAFE_RETAIN(body);
        this->body = body;
        this->body->setPosition(Point(868,50));
        this->faces->addObject(mainFace);
    }
//        else if (this->characterId == CHAR_GOVERMENT) {
//        FaceBone* mainFace = new FaceBone(ANI_JSON_GOVERMENT, ANI_ATLAS_GOVERMENT);
//        mainFace->setVisible(true);
//        mainFace->setAnimation("Tan cong", true);
//        RectBody* body = new RectBody(230,205);
//        body->setFlipX(true);
//        CC_SAFE_RETAIN(body);
//        this->body = body;
//        this->body->setPosition(Point(868,324));
//        this->faces->addObject(mainFace);
//    }
}

void Character::upgradeCharacter(int specialLevel)
{
    
    char* normalStatePattern = (char*) "";
    
    if(this->getCharacterId() == CHAR_KID){
        char normalSpriteFrame[200];
        sprintf(normalSpriteFrame, "lv%d", specialLevel + 1);
        FaceBone* mainFace = (FaceBone*)this->faces->getObjectAtIndex(0);
        mainFace->setSkin(normalSpriteFrame);
    } else {
        normalStatePattern = this->getAnimation();
        char normalSpriteFrame[200];
        sprintf(normalSpriteFrame, normalStatePattern, specialLevel);

        Face* mainFace = (Face*)this->faces->getObjectAtIndex(0);
        mainFace->setSpriteFrame(normalSpriteFrame);
    }
    
}

void Character::upLevel(EntityCharacter* ettCharacter, int level, int specialLevel) {
    //update special Level
    BigNumber* newBaseDps = BigNumber::create();
    newBaseDps->initialize(0);
    if (specialLevel>=0){
        newBaseDps = ettCharacter->getDps();
        this->upgradeCharacter(specialLevel);
    }
     __Array *avatars = ettCharacter->getAvatars();
    for(int i=1;i<=specialLevel;i++)
    {
        EntityCharacterAvatar* avatar = (EntityCharacterAvatar*)avatars->getObjectAtIndex(i);
        newBaseDps = newBaseDps->add(avatar->getAddingUnit());
        newBaseDps = newBaseDps->multiplyRationalNumber(avatar->getMulUnit());
    }
    this->upgradeLevel = specialLevel;
    //update level
    if (level <= 0) {
        auto tempCost = this->cost;
        Utils::safeRelease(tempCost);
        this->cost = BigNumber::create();
        CC_SAFE_RETAIN(this->cost);
        char* baseCostString = ettCharacter->getCost()->toString();
        this->cost->initialize(baseCostString);
        delete[] baseCostString;
        
        this->attackTime = ettCharacter->getAttackTime();
        
        auto dpsTemp = this->dps;
        Utils::safeRelease(dpsTemp);
        this->dps = BigNumber::create();
        CC_SAFE_RETAIN(this->dps);
        char* baseDpsString = ettCharacter->getDps()->toString();
        this->dps->initialize(baseDpsString);
        delete[] baseDpsString;
        
        this->level = level;
    } else {
        BigNumber* levelBig = BigNumber::create();
        levelBig->initialize(level);
        //update cost
        auto tempCost = this->cost;
        this->cost = ettCharacter->getCost()->multiplyRationalNumber(pow(1.1f,level));
        CC_SAFE_RETAIN(this->cost);
        Utils::safeRelease(tempCost);
        //update attackTime
        this->attackTime = ettCharacter->getAttackTime();
        //update Dps
        auto tempDps = this->dps;
        this->dps = newBaseDps->complexMultiply(levelBig);
        CC_SAFE_RETAIN(this->dps);
        Utils::safeRelease(tempDps);
        this->level = level;
        
    }
}
char* Character::getAnimation()
{
     char* normalStatePattern = (char*) "";
    if (this->characterId == CHAR_CEO) {
        normalStatePattern = (char*) ANI_CHAR_CEO;
    } else if (this->characterId == CHAR_GHOST) {
        normalStatePattern = (char*) ANI_CHAR_GHOST;
    } else if (this->characterId == CHAR_GOD) {
        normalStatePattern = (char*) ANI_CHAR_GOD;
    } else if (this->characterId == CHAR_GOVERMENT) {
        normalStatePattern = (char*) ANI_CHAR_GOVERMENT;
    } else if (this->characterId == CHAR_GRANDMA) {
        normalStatePattern = (char*) ANI_CHAR_GRANDMA;
    } else if (this->characterId == CHAR_HACKER) {
        normalStatePattern = (char*) ANI_CHAR_HACKER;
    } else if (this->characterId == CHAR_KID) {
        normalStatePattern = (char*) ANI_CHAR_KID;
    } else if (this->characterId == CHAR_SUPER_MAN) {
        normalStatePattern = (char*) ANI_CHAR_SUPER_MAN;
    } else if (this->characterId == CHAR_GAME_DEV) {
        normalStatePattern = (char*) ANI_CHAR_GAME_DEV;
    }
    return normalStatePattern;
}
int Character::getNextLevel() {
    return this->level + 1;
}


void Character::initUpgradeLevel(int numberOfUpgradeLevel)
{
    for(int i=0;i<numberOfUpgradeLevel;i++)
    {
        BigNumber* levelEarn = BigNumber::create();
        levelEarn->initialize(0);
        this->upgradeLevelEarn->addObject(levelEarn);
    }
}